package com.alinesno.cloud.monitor.agent.collect;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSONObject;
import com.alinesno.cloud.monitor.agent.aspect.BaseAspect;
import com.alinesno.cloud.monitor.agent.dto.web.RequestURLDto;
import com.alinesno.cloud.monitor.agent.tool.IPUtils;

/**
 * URL 访问监控
 * 
 * @author WeiXiaoJin
 * @since 2019年9月17日 下午10:04:28
 */
@Aspect
@Component
public class WatcherControllerMethonAspect extends BaseAspect {

	@SuppressWarnings("unused")
	private static final Logger log = LoggerFactory.getLogger(WatcherControllerMethonAspect.class);

	/**
	 * URL请求
	 */
	@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
	public void pointcut() {
	}

	// 统计请求的处理时间
	ThreadLocal<Long> startTime = new ThreadLocal<>();

	@Around("pointcut()")
	public Object around(ProceedingJoinPoint point) {
		Object result = null;
		StopWatch watch = StopWatch.createStarted() ; 
		try {
			// 执行方法
			result = point.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		// 执行时长(毫秒)
		watch.stop();  
		long time = watch.getTime() ; 

		// 保存日志
		monitorAccountOperator(point, time);
		return result;
	}

	/**
	 * 记录用户操作日志
	 * 
	 * @param joinPoint
	 * @param time
	 */
	public void monitorAccountOperator(ProceedingJoinPoint joinPoint, long time) {
		RequestURLDto bean = new RequestURLDto();

		bean.setMethodTime(time);
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		String className = joinPoint.getTarget().getClass().getName(); // 请求的方法名
		String methodName = signature.getName();
		bean.setMethod(className + ":" + methodName);

		RequestMapping mvcRequest = method.getAnnotation(RequestMapping.class);
		String value = mvcRequest.value() + "" ;

		bean.setMethodDesc(value);

		// 请求的方法参数值 请求的方法参数名称
		Object[] args = joinPoint.getArgs();
		LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();

		String[] paramNames = u.getParameterNames(method);
		if (args != null && paramNames != null) {
			String params = "";
			for (int i = 0; i < args.length; i++) {
				params += "  " + paramNames[i] + ": " + args[i];
			}
			bean.setParams(params);
		}

		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		String agent = request.getHeader("User-Agent");
		String url = request.getRequestURL().toString();

		bean.setIp(IPUtils.getIpAddr(request));
		bean.setUrl(url);
		bean.setAgent(agent);
		
		bean.setHostname(IPUtils.HOSTNAME);
		bean.setApplicationName(applicationName);

		// 设置用户
//		Object account = request.getSession().getAttribute("CurrentUser");
//		if (account != null) {
//			bean.setAccountId(account.getId());
//			bean.setAccountName(account.getName());
//			bean.setApplicationId(account.getApplicationId());
//			bean.setLoginName(account.getLoginName());
//
//			bean.setOperatorId(account.getId());
//		}
//		bean.setCreateTime(System.currentTimeMillis());
//
//		if (saveOperationLogger) {
//			managerAccountRecordService.save(bean);
//		}

		kafkaProducer.asyncSendMessage(WATCHER_TOPIC_WEB_CONTROLLER , JSONObject.toJSONString(bean)); 
	}
}
